#pragma once
#include<iostream>
#include<string>
#include<jsoncpp/json/json.h>

namespace protocol_ns
{
    const std::string SEP = "\r\n";
    std::string Encode(const std::string &json_str)
    {
        int json_str_len = json_str.size();
        std::string proto_str = std::to_string(json_str_len);
        proto_str += SEP;
        proto_str+=json_str;
        proto_str+=SEP;
        return proto_str;
    }
    std::string Decode(std::string &inbuffer)
    {
        auto pos = inbuffer.find(SEP);
        if(pos==std::string::npos)
        {
            return std::string();
        }
        std::string len_str = inbuffer.substr(0,pos);
        if(len_str.empty())
        {
            return std::string();
        }
        int packlen = std::stoi(len_str);//字符串转换整型
        int total = packlen+len_str.size()+2*SEP.size();
        if(inbuffer.size()<total)
        {
            return std::string();
        }
        std::string package = inbuffer.substr(pos+SEP.size(),packlen );
        inbuffer.erase(0,total);
        return package;
    }

    //报文 = 报头+有效载荷
    class Request
    {
        public:
        Request()
        {}
        Request(int x,int y ,int oper)
        :_x(x)
        ,_y(y)
        ,_oper(oper)
        {}
        bool Serialize(std::string *out)//序列化
        {
            Json::Value root;
            root["y"] = _x;
            root["y"] = _y;
            root["oper"] = _oper;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
        }
        bool Deserialize(const std::string &in)//反序列化
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in,root);
            if(!res)
            {
                return false;
            }
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
        }
        public:
        int _x;
        int _y;
        char _oper;
    };

    class Response
    {
        public:
        Response()
        {}
        Response(int result,int code)
            :_result(result)
            ,_code(code)
        {}
        bool Serialize(std::string *out)
        {
            Json::Value root;
            root["_result"] = _result;
            root["code"] = _code;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
        }
        bool Deserialize(const std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in,root);
            if(!res)
            {
                return false;
            }
            _result = root["result"].asInt();
           _code =  root["code"] .asInt();
           return true;
        }
        public:
        int _result;
        int _code;
    };
    class Factory
    {
        public:
        Factory()
        {
            srand(time(nullptr)^getpid());
            opers = "+/*/%^&|";
        }
        std::shared_ptr<Request> BuildRequest()
        {
            int x = rand() % 10 + 1;
            usleep(x * 10);
            int y = rand() % 5; // [01,2,3,4]
            usleep(y * x * 5);
            char oper = opers[rand() % opers.size()];
            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, oper);
            return req;
        }
        std::shared_ptr<Response>BuildResonse()
        {
            return std::make_shared<Response>();
        }
        ~Factory()
        {}
        private:
        std::string opers;
    };
}